/*
 * @Author: 王炜皓
 * @Date: 2023-05-15 19:09:23
 * @LastEditTime: 2023-07-28 16:15:52
 * @LastEditors: 王炜皓
 * @Description: UTUM cesium SDK
 * @FilePath: \cesium-tool\src\views\test\UTUM3d.ts
 */
const Cesium = window.Cesium;

import * as turf from "@turf/turf";
import Weather from './extend/weather/weather'
import Rotate from './extend/rotate/rotate'
import Draw from './extend/Draw/Draw'
import Roaming from './extend/roaming/Roaming'
import Analyse from './extend/analyse/analyse'
import Tile from './extend/tile/tile'
import Effect from './extend/effect/index'

import HeatMap from './extend/heatMap/Heatmap'
import AmapImageryLayerProvider from "./extend/AmapImageryLayerProvider/AmapImageryLayerProvider.js";
import BaiduImageryLayerProvider from "./extend/BaiduImageryLayerProvider/BaiduImageryLayerProvider.js";
import CreatePolyline from './extend/Draw/BrokenLine/CreatePolyline'
import CreateCircle from "./extend/Draw/Circle/CreateCircle";

import CreateRegularPolygon from "./extend/Draw/Polygon/CreatePolygon";
import EditPolygon from "./extend/Draw/Polygon/EditPolygon.js";
import CreateRandom from "./extend/Draw/random/Createrandom.js";
import CreateArrow from "./extend/Draw/Arrow/CreateArrow";
import EditArrow from "./extend/Draw/Arrow/editArrow.js";
import CoordTransform from "./extend/CoodTransform";
import SlopeAspect from "./extend/analyse/slope/SlopeAspect.js";
import ContourAnalysis from "./extend/analyse/contour/ContourAnalysis";
import CreatePolygonOnGround from "./extend/analyse/slope/CreatePolygonOnGround.js";
import CreatePolygonForExcavation from "./extend/analyse/excavation/CreatePolygon.js";
import Excavation from "./extend/analyse/excavation/excavation.js";
import EditB3DM from "./extend/editB3Dm/editB3DM.js";
import { captureScreenshot, blobToBase64 } from "./extend/captureScreen/captureScreen.js";
import SceneRoaming from "./extend/roaming/ScreenRoaming.js";
import { ElMessage } from "element-plus";
import HeatmapIntensity from "./extend/heatMap/HeatmapIntensity.js"
import KrigingHeatmapIntensity from './extend/heatMap/kriging.js'
import Section from './extend/section/section.js'
interface EntityData  {
  name: string;
  type: string;
  special_attributes:any;
  location: {
    longitude: number;
    latitude: number;
  };
}
interface EntityInfo  {
  viewer:any,
  data:Array<EntityData>,
  tributeMap:Map<string, any>,
  imgMap:Map<string, any>
  htmlId:string
}
export class W3d {
  view: any;
  corentBaseMap: any;
  intMap: any;
  handler: any;
  pickerEntity: any; //正在选择的实体
  measureEntity: Array<any>; //测量的实体id
  maskpolygonEntity: Array<any>; //遮罩层实体
  changeDepth: boolean; //深度检测改变
  WaterAnalyseID: Array<any>;
  editObj: any;
  static Weather =Weather;//天气
  static Rotate =Rotate;//旋转
   _Draw :any;
   _Roaming:any;
   _Analyse:any;
   _Tile:any;
   _HeatMap:any;
   _Effect:any
  // static HeatMap = HeatmapIntensity;//热力图类
  // static Kriging = KrigingHeatmapIntensity;//克里金插值
  static Section=Section;//剖切
  constructor() {
    this.measureEntity = [];
    this.maskpolygonEntity = [];
    this.changeDepth = false;
    this.WaterAnalyseID = [];
  }
 get Draw(){
  return this._Draw
 }
 get Roaming(){
  return this._Roaming
 }
 get Analyse(){
  return this._Analyse
 }
 get HeatMap(){
  return this._HeatMap
 }
 get Tile(){
  return this._Tile
 }
 get Effect(){
  return this._Effect
 }
  createmap() {
    let keyid = "26d2e97bdbaa68c5a47117f95eff0d98";
    this.intMap = new Cesium.WebMapTileServiceImageryProvider({
      url:
        "https://{s}.tianditu.gov.cn/vec_c/wmts?service=wmts&request=GetTile&version=1.0.0" +
        "&LAYER=vec&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" +
        "&style=default&format=tiles&tk=" +
        keyid,
      layer: "tdtImg_c",
      style: "default",
      format: "tiles",
      tileMatrixSetID: "c",
      subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
      tilingScheme: new Cesium.GeographicTilingScheme(),
      tileMatrixLabels: [
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "10",
        "11",
        "12",
        "13",
        "14",
        "15",
        "16",
        "17",
        "18",
        "19",
      ],

      maximumLevel: 50,
    });
    let key =
      "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJiYjUwNWQyOC0yZmZhLTRmMzItOTQyZC02ZmQyMWIyMTA3NmEiLCJpZCI6NjcyNzcsImlhdCI6MTY2ODE1ODc2Mn0.t1h6-ZADkGnZUZZoLtrlgtTp8_MR2Kxfhew42ksDgmk";
    Cesium.Ion.defaultAccessToken = key;
    this.view = window.Viewer = new Cesium.Viewer("cesiumContainer", {
      imageryProvider: this.intMap,
      // terrainProvider: Cesium.createWorldTerrain(),
      geocoder: false,
      homeButton: false,
      sceneModePicker: false,
      baseLayerPicker: false,
      navigationHelpButton: false,
      animation: false,
      timeline: false,
      fullscreenButton: false,
      vrButton: false,
      //关闭点选出现的提示框
      selectionIndicator: false,
      infoBox: false,
    });
    this.view.scene.debugShowFramesPerSecond = true;
    this.view.scene.globe.depthTestAgainstTerrain = false;
    this.view.cesiumWidget.screenSpaceEventHandler.removeInputAction(
      Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
    ); //取消双击事件
    this.view._cesiumWidget._creditContainer.style.display = "none"; // 隐藏版权
    this._Draw=new Draw(this.view)
    this._Roaming=new Roaming(this.view)
    this._Analyse=new Analyse(this.view)
    this._HeatMap=new HeatMap(this.view)
    this._Tile=new Tile(this.view)
    console.log('eeee',this._Tile);
    
    this._Effect=new Effect(this.view)

  }
  View() {
    return this.view;
  }
  flyTo(viewer:any, type:any, destination: Array<any>, orientation: Array<any>) {
    // 设置相机位置
    if (type == "xyz") {
      let orientationTOc =
        orientation.length > 0
          ? {
              // 初始视角
              heading: orientation[0],
              pitch: orientation[1],
              roll: orientation[2],
            }
          : {
              heading: Cesium.Math.toRadians(0),
              pitch: Cesium.Math.toRadians(90),
              roll: Cesium.Math.toRadians(0),
            };
      viewer.camera.setView({
        // 设置相机位置
        destination: {
          x: destination[0],
          y: destination[1],
          z: destination[2],
        },

        orientation: orientationTOc,
      });
    }
    if (type == "ll") {
      viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(
          destination[0],
          destination[1],
          destination[2] || 10000
        ),
        orientation: {
          heading: Cesium.Math.toRadians(0),
          pitch: Cesium.Math.toRadians(-90),
          roll: Cesium.Math.toRadians(0),
        },
      });
    }
  }
   
  // addEntity(viewer:any,entityData:Array<EntityData>,myMap: Map<string, any>,entyImgMap:Map<string, any>){
    addEntity(info:EntityInfo){
    let billBordEntities
    const {viewer,data,tributeMap,imgMap,htmlId}=info

    data.forEach((item)=>{
      let billBordEntity =new Cesium.Entity({
        name: item.name,
        position: Cesium.Cartesian3.fromDegrees(item.location.longitude, item.location.latitude),
        billboard: new Cesium.BillboardGraphics({
          image: imgMap.get(item.type), // 广告牌图片的路径
          width: 42, // 宽度
          height: 42, // 高度
          // 这里可以添加更多的广告牌属性
        }),
        label: { //文字标签
          text: item.name,
          font: '20px sans-serif',
          fillColor: Cesium.Color.BLACK, // 文字颜色为黑色
          backgroundColor: Cesium.Color.TRANSPARENT, // 背景色透明
          showBackground: false, // 不显示背景
          horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // 水平居中
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直定位于底部
          pixelOffset: new Cesium.Cartesian2(0, 20), // 向下偏移以放置在 billboard 下方
          pixelOffsetScaleByDistance: new Cesium.NearFarScalar(1.5e2, 3.0, 1.5e7, 0.5)
          },
          properties:item.special_attributes,
          location:item.location
      });
      viewer.entities.add(billBordEntity)
      
  

    })

  }
  createPolygonLine(viewer:any, option:any, callbackForInfo:any) {
    if (this.handler) this.handler.destroy();
    this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    const resultList = [];
    const callback = (event) => {
      console.log(event, "event");
      if (callbackForInfo && typeof callbackForInfo == "function")
        callbackForInfo(event);
    };
    CreatePolyline(viewer, this.handler, resultList, option, callback);
  }
  createPolygon(viewer:any, option:any, callbackForInfo:any) {
    if (this.handler) this.handler.destroy();
    this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    const resultList = [];
    const callback = (event) => {
      console.log(event, "event");
      if (callbackForInfo && typeof callbackForInfo == "function")
        callbackForInfo(event);
    };
    CreateRegularPolygon(viewer, this.handler, resultList, option, callback);
  }
  // 获取现在相机位置
  getCorrentCameraPosition(viewer:any) {
    if (!viewer) throw new Error("请初始化viewer");
    var head = viewer.scene.camera.heading;
    var pitch = viewer.scene.camera.pitch;
    var roll = viewer.scene.camera.roll;
    var info = { head: head, pitch: pitch, roll: roll };
    // 获取位置 wgs84的地心坐标系，x,y坐标值以弧度来表示
    var position = viewer.scene.camera.positionCartographic; //经纬度单位为弧度，高程单位为米.
    //以下方式也可以获取相机位置只是返回的坐标系不一样
    // var position = this.viewer.scene.camera.position //cartesian3 空间直角坐标系
    // var ellipsoid = scene.globe.ellipsoid;
    // var position =ellipsoid.cartesianToCartographic(this.viewer.scene.camera.position)//
    // 弧度转经纬度
    var longitude = Cesium.Math.toDegrees(position.longitude).toFixed(6);
    var latitude = Cesium.Math.toDegrees(position.latitude).toFixed(6);
    var height = position.height;
    return { lng: longitude, lat: latitude, h: height, mat: info };
  }
  // 获取鼠标位置
  getMousePosition(viewer:any) {
    if (!viewer) throw new Error("请初始化viewer");
    var cesiumViewer = viewer;
    var canvas = cesiumViewer.scene.canvas;
    //得到当前三维场景的椭球体
    var ellipsoid = cesiumViewer.scene.globe.ellipsoid;
    // 定义当前场景的画布元素的事件处理
    var handler = new Cesium.ScreenSpaceEventHandler(canvas);
    let lat;
    let lng;
    let height;
    //设置鼠标移动事件的处理函数，这里负责监听x,y坐标值变化
    handler.setInputAction(function (movement) {
      //捕获椭球体，将笛卡尔二维平面坐标转为椭球体的笛卡尔三维坐标，返回球体表面的点
      var cartesian = cesiumViewer.camera.pickEllipsoid(
        movement.endPosition,
        ellipsoid
      );
      if (cartesian) {
        //将笛卡尔三维坐标转为地图坐标（弧度）
        var cartographic =
          cesiumViewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
        //将地图坐标（弧度）转为十进制的度数
        lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(4);
        lng = Cesium.Math.toDegrees(cartographic.longitude).toFixed(4);
        height = (
          cesiumViewer.camera.positionCartographic.height / 1000
        ).toFixed(2);

        // console.log(lng+','+lat+","+height);
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); //此枚举类型用于对鼠标事件进行分类:向下、向上、单击、双击、按住按钮时移动和移动。具体参考文档Cesium.ScreenSpaceEventType
    return { lat: lat, lng: lng, height: height };
  }
  //获取比例尺
  getScale(viewer:any) {
    if (!viewer) throw new Error("请初始化viewer");

    // 创建比例尺控件

    // 创建比例尺控件
    var geodesic = new Cesium.EllipsoidGeodesic();
    let scene = viewer.scene;
    let width = scene.canvas.clientWidth;
    let height = scene.canvas.clientHeight;
    let left = scene.camera.getPickRay(new Cesium.Cartesian2(0, height / 2));
    let right = scene.camera.getPickRay(
      new Cesium.Cartesian2(width, height / 2)
    );
    let globe = scene.globe;
    let leftPosition = globe.pick(left, scene);
    let rightPosition = globe.pick(right, scene);
    if (!leftPosition) return;
    let leftCartographic =
      globe.ellipsoid.cartesianToCartographic(leftPosition);
    let rightCartographic =
      globe.ellipsoid.cartesianToCartographic(rightPosition);
    geodesic.setEndPoints(leftCartographic, rightCartographic);
    //根据屏幕左侧到右侧的距离测算resolution
    let pixelDistance = geodesic.surfaceDistance;
    let resolution = pixelDistance / width;
    let scale = (resolution * 96) / 0.0254;
    return scale;
  }
  // 天地图加载
  tdtWebServer(url:any) {
    return new Cesium.WebMapTileServiceImageryProvider({
      //调用影响中文注记服务
      url: url,
      layer: "tdtImg_c",
      style: "default",
      format: "tiles",
      tileMatrixSetID: "c",
      subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
      tilingScheme: new Cesium.GeographicTilingScheme(),
      tileMatrixLabels: [
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9",
        "10",
        "11",
        "12",
        "13",
        "14",
        "15",
        "16",
        "17",
        "18",
        "19",
      ],
      maximumLevel: 50,
    });
  }
  //切换底图
  changeBaseMap(type:any, viewer:any, key:any) {
    if (!viewer) throw new Error("请初始化viewer");
    if (!type) throw new Error("请填写底图类型type");
    if (!key) throw new Error("请填写天地图底图KEY");
    var TDT_CVA_W =
      "https://{s}.tianditu.gov.cn/cva_w/wmts?service=wmts&request=GetTile&version=1.0.0" +
      "&LAYER=cva&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" +
      "&style=default.jpg&tk=自己的申请的tk";
    var TDT_CIA_C =
      "https://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0" +
      "&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" +
      "&style=default&format=tiles&tk=" +
      key;
    const tdtVecImageryProvider = this.tdtWebServer(TDT_CVA_W);
    const tdtImgImageryProvider = this.intMap;
    const tdtCiaImageryProvider = this.tdtWebServer(TDT_CIA_C);
    const arcgisMAp = new Cesium.ArcGisMapServerImageryProvider({
      url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
    });
    const gdStreatMap = new AmapImageryLayerProvider({
      url: "https://wprd{s}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&sci=1&style=7",
      crs: "WGS84",
    });
    const gdImgStreatMap = new AmapImageryLayerProvider({
      url: "https://wprd{s}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&sci=1&style=6",
      crs: "WGS84",
    });
    const baiduVecImage = new BaiduImageryLayerProvider({
      url: "https://online{s}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=sl&v=020",
      crs: "WGS84",
      style: "nomal",
    });
    const baiduImgImage = new BaiduImageryLayerProvider({
      url: "https://shangetu{s}.map.bdimg.com/it/u=x={x};y={y};z={z};v=009;type=sate&fm=46",
      crs: "WGS84",
      style: "nomal",
    });
    var resolutions = [
      0.7031249999891493, 0.3515624999945734, 0.17578124999728698,
      0.08789062499864363, 0.04394531249932181, 0.021972656249660875,
      0.010986328124830453, 0.005493164062415213, 0.0027465820312075943,
      0.0013732910156038045, 0.0006866455078019049, 0.0003433227539009499,
      0.0001716613769504757, 0.00008583068847523785, 0.0000429153442376188,
    ];
    var matrixIds = [];
    var projectionExtent = Cesium.Rectangle.fromDegrees(-180, -90, 180, 90);
    for (var i = 0; i < resolutions.length; i++) {
      (matrixIds as Array<number>).push(i as any);
    }
    console.log(matrixIds, "matrixIds");

    let dzkey =
      "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJjYzU4MmFjNC1kMjNjLTRkMGYtOTY3MS05MTkyMmM5ZjNjOTgifQ.hp9QAVE1gnLTWTLLYWMvdpObR4-eA0IV5WZFOmEl6jo";
    const dzImage = new Cesium.WebMapTileServiceImageryProvider({
      // url : 'https://igss.cgs.gov.cn:6160/igs/rest/ogc/qg250w_20220913/WMTSServer?tk='+dzkey+'&Width=256&Height=256&tilematrixset=EPSG:4326_qg250w_20210416_ZAZSeOGX_028mm_GB',
      url:
        "https://igss.cgs.gov.cn:6160/igs/rest/ogc/qg250w_20220913/WMTSServer/1.0.0/WMTSCapabilities.xml?tk=" +
        dzkey,
      layer: "qg250w_20220913",
      style: "default",
      format: "image/png",
      tileMatrixSetID:
        "EPSG:4326_ChinaGeologicalMap_20201207_va8mWXHb_028mm_GB",
      tileMatrixLabels: matrixIds,
      maximumLevel: resolutions.length - 1,
      credit: "",
    });

    if (this.corentBaseMap) {
      console.log("存在");

      viewer.imageryLayers.remove(this.corentBaseMap);
    } else {
      console.log(this.intMap, this.corentBaseMap, "不存在");

      // this.corentBaseMap = this.intMap;
      viewer.imageryLayers.remove(this.intMap);
    }
    const myMap = new Map();
    myMap.set("tdt_vec", tdtVecImageryProvider);
    myMap.set("tdt_img", tdtImgImageryProvider);
    myMap.set("tdt_cia", tdtCiaImageryProvider);
    myMap.set("gd_bz", gdStreatMap);
    myMap.set("gd_img", gdImgStreatMap);
    myMap.set("arc", arcgisMAp);
    myMap.set("bd_vec", baiduVecImage);
    myMap.set("bd_img", baiduImgImage);
    myMap.set("dz", dzImage);

    //两次点击相同图层
    if (myMap.get(type) == this.corentBaseMap) {
      console.log("重复点击");

      return;
    }
    console.log(type, "map");
    if (!myMap.get(type)) throw new Error("type填写错误");
    this.corentBaseMap = myMap.get(type);
    viewer.imageryLayers.addImageryProvider(myMap.get(type));
  }
  //获取当前点击对象
  getPicking(handler:any, viewer:any, callback:any, openTripParemeter:any) {
    // 创建一个ScreenSpaceEventHandler对象
    let _this = this;
    handler.setInputAction(function (click:any) {
      console.log("getPicking正在拾取坐标");

      var position = click.position;
      var pickedObject = viewer.scene.pick(position);
      // 检查pickedObject是否为实体
      if (
        Cesium.defined(pickedObject) &&
        Cesium.defined(pickedObject.id) &&
        pickedObject.id instanceof Cesium.Entity
      ) {
        // 获取点击的实体+
        var entity = pickedObject.id;
        // 输出实体信息
        const toolTip = pickedObject.id;
        _this.pickerEntity = entity;
        if (callback && typeof callback == "function") callback(entity);
        if (openTripParemeter && typeof openTripParemeter == "string")
          _this.createRemindertip(
            entity[openTripParemeter],
            click.position,
            true
          );
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  }
  //摧毁提示框
  destroyTip() {
    let tooltip = document.getElementById("toolTip");
    if (tooltip) (tooltip as any).style.display = "none";
  }
  // 生成提示框随鼠标移动
  createRemindertip(arr: any, position: any, show: boolean) {
    let tooltip = document.getElementById("toolTip");
    let style: any, _x: number, _y: number;
    let _color: string = "";
    if (arr && typeof arr === "object") {
      style = arr;
    }
    if (style && style.origin) {
      style.origin === "center" && ((_x = 15), (_y = -12));
      style.origin === "top" && ((_x = 15), (_y = -44));
      style.origin === "bottom" && ((_x = 15), (_y = 20));
    } else {
      (_x = 15), (_y = 20);
    }
    if (style && style.color) {
      style.color === "white" &&
        (_color = "background: rgba(255, 255, 255, 0.8);color: black;");
      style.color === "black" &&
        (_color = "background: rgba(0, 0, 0, 0.8);color: white;");
      style.color === "yellow" &&
        (_color =
          "color: black;background-color: #ffcc33;border: 1px solid white;");
    } else {
      _color = "background: rgba(0, 0, 0, 0.8);color: white;";
    }
    if (tooltip === null) {
      const viewerDom = document.getElementsByClassName("cesium-viewer")[0];
      let elementbottom = document.createElement("div");
      viewerDom.append(elementbottom);
      let html =
        '<div id="toolTip" style="display: none;pointer-events: none;position: absolute;z-index: 1000;opacity: 0.8;border-radius: 4px;padding: 4px 8px;white-space: nowrap;font-family:黑体;color:white;font-weight: bolder;font-size: 14px;' +
        _color +
        '"></div>';
      viewerDom.insertAdjacentHTML("beforeend", html);
      tooltip = document.getElementById("toolTip");
    }
    if (show) {
      tooltip!.innerHTML = arr;
      tooltip!.style.left = position.x + _x! + "px";
      tooltip!.style.top = position.y + _y! + "px";
      tooltip!.style.display = "block";
    } else {
      tooltip!.style.display = "none";
    }
    return {
      tooltip: tooltip,
      style: style,
      showAt: function (position: any, text: any) {
        this.tooltip!.innerHTML = text;
        if (this.style && this.style.origin) {
          this.style.origin === "center" &&
            ((_x = 15), (_y = -this.tooltip!.offsetHeight / 2));
          this.style.origin === "top" &&
            ((_x = 15), (_y = -this.tooltip!.offsetHeight - 20));
          this.style.origin === "bottom" && ((_x = 15), (_y = 20));
        } else {
          (_x = 15), (_y = -this.tooltip!.offsetHeight / 2);
        }
        this.tooltip!.style.left = position.x + _x + "px";
        this.tooltip!.style.top = position.y + _y + "px";
        this.tooltip!.style.display = "block";
      },
      show: function (show: boolean) {
        if (show) {
          this.tooltip!.style.display = "block";
        } else {
          this.tooltip!.style.display = "none";
        }
      },
    };
  }
  //生成随机数{
  newSessionid(num?: number) {
    let len = num || 32;
    let chars =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    let maxPos = chars.length;
    let pwd = "";
    for (let i = 0; i < len; i++) {
      pwd += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
  }
  // #xxx hev格式转cesiumColor
  hexToCesiumColor(hex:any, alpha:any) {
    // 去除可能存在的 # 符号
    hex = hex.replace("#", "");

    // 提取红色、绿色和蓝色分量
    var red = parseInt(hex.substring(0, 2), 16) / 255;
    var green = parseInt(hex.substring(2, 4), 16) / 255;
    var blue = parseInt(hex.substring(4, 6), 16) / 255;

    // 创建并返回 Cesium.Color 对象
    return new Cesium.Color(red, green, blue, alpha);
  }
  // RGB格式转#xxx hev
  convertColorToHex(color:any) {
    const red = Math.floor(color.red * 255)
      .toString(16)
      .padStart(2, "0");
    const green = Math.floor(color.green * 255)
      .toString(16)
      .padStart(2, "0");
    const blue = Math.floor(color.blue * 255)
      .toString(16)
      .padStart(2, "0");
    return `#${red}${green}${blue}`;
  }
  //获取比例尺
  GetScale(viewer:any) {
    // 创建比例尺控件
    // 创建比例尺控件
    var geodesic = new Cesium.EllipsoidGeodesic();
    let scene = viewer.scene;
    let width = scene.canvas.clientWidth;
    let height = scene.canvas.clientHeight;
    let left = scene.camera.getPickRay(new Cesium.Cartesian2(0, height / 2));
    let right = scene.camera.getPickRay(
      new Cesium.Cartesian2(width, height / 2)
    );
    let globe = scene.globe;
    let leftPosition = globe.pick(left, scene);
    let rightPosition = globe.pick(right, scene);
    if (!leftPosition) return;
    let leftCartographic =
      globe.ellipsoid.cartesianToCartographic(leftPosition);
    let rightCartographic =
      globe.ellipsoid.cartesianToCartographic(rightPosition);
    geodesic.setEndPoints(leftCartographic, rightCartographic);
    //根据屏幕左侧到右侧的距离测算resolution
    let pixelDistance = geodesic.surfaceDistance;
    let resolution = pixelDistance / width;
    let scale = (resolution * 96) / 0.0254;
    console.log(scale, "scale");

    return scale;
  }
  // 测量距离
  measureDisatance(viewer:any) {
    console.log("measure");

    const callback = (event) => {
      this.measureEntity.push(event);
      for (let i = 0; i <= event.PottingPoint.length; i++) {
        let start = event.PottingPoint[i];
        let end = event.PottingPoint[i + 1];
        let distance = this.getLength(start, end);
        let mid = this.getMidpoint(start, end);
        const callbackfoeID = (e) => {
          this.measureEntity.push(e);
        };
        this.addLabel(viewer, mid, distance + "km", callbackfoeID, "中点");
      }
    };
    this.createPolygonLine(viewer, {}, callback);
  }
  // 测量面积
  measureArea(viewer:any) {
    const callback = (event) => {
      console.log(event, "sdsdsds");
      this.measureEntity.push(event);
      let result = CoordTransform.Cartesian3ListToWGS84AltLess(
        event.PottingPoint.positions
      );
      //放入第一个点组成封闭多边形
      result.push(result[0]);
      var polygon = turf.polygon([result]);
      const callbackfoeEntity = (e) => {
        this.measureEntity.push(e);
      };
      let area = turf.area(polygon) / 10 ** 6;
      this.addLabel(
        viewer,
        event.PottingPoint.positions[0],
        area.toFixed(2) + "km²",
        callbackfoeEntity,
        "体积"
      );
    };
    this.createPolygon(viewer, {}, callback);
  }
  //移除所有测量实体
  removeAllMeasure(viewer:any) {
    if (this.measureEntity.length > 0) {
      for (let item of this.measureEntity) viewer.entities.remove(item);
    }
  }
  /* 空间两点距离计算函数 */
  getLength(start:any, end:any) {
    // 将起点与终点位置信息从笛卡尔坐标形式转换为Cartographic形式
    let startCartographic = Cesium.Cartographic.fromCartesian(start);
    let endCartographic = Cesium.Cartographic.fromCartesian(end);
    // 初始化测地线
    let geodesic = new Cesium.EllipsoidGeodesic();
    // 设置测地线起点和终点，EllipsoidGeodesic中setEndPoints常与surfaceDistance搭配使用
    geodesic.setEndPoints(startCartographic, endCartographic);
    // 获取起点和终点之间的表面距离，单位为km，规定四舍五入保留两位小数
    // surfaceDistance返回number 单位为m，带小数
    // console.log((geodesic.surfaceDistance / 1000).toFixed(2))
    return (geodesic.surfaceDistance / 1000).toFixed(2);
  }
  /* 空间两点计算中点函数 */
  getMidpoint(start:any, end:any) {
    let startPoint = Cesium.Cartographic.fromCartesian(start);
    let endPoint = Cesium.Cartographic.fromCartesian(end);
    let geodesic = new Cesium.EllipsoidGeodesic();
    geodesic.setEndPoints(startPoint, endPoint);
    let geoPoint = geodesic.interpolateUsingFraction(0.5);
    console.log(Cesium.Ellipsoid.WGS84.cartographicToCartesian(geoPoint));
    return Cesium.Ellipsoid.WGS84.cartographicToCartesian(geoPoint);
  }
  /* 在视图中添加标签 */
  addLabel(viewer:any, position:any, label:any, callback:any, name:any) {
    if (!name) name = this.newSessionid(32);
    let id = this.newSessionid(32);
    let entity = viewer.entities.add({
      name: name,
      id: id,
      position: position,
      label: {
        text: label,
        font: "20px sans-serif",
        fillColor: Cesium.Color.WHITE,
        outlineWidth: 2,
        backgroundColor: Cesium.Color.BLACK,
        showBackground: true,
        style: Cesium.LabelStyle.FILL,
        verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      },
    });
    if (callback && typeof callback == "function") callback(entity);
    // let viewer = this.viewer
    return entity;
  }
  // 开启地下模式
  openUnderGroundPattern(viewer:any) {
    viewer.scene.screenSpaceCameraController.enableCollisionDetection = false; //相机与地形的碰撞检测
    viewer.scene.globe.translucency.frontFaceAlphaByDistance =
      new Cesium.NearFarScalar(1.5e2, 0.5, 8.0e6, 1.0);
    viewer.scene.globe.translucency.enabled = true; //是否开启透明
  }
  // 关闭地下模式
  closeUnderGroundPattern(viewer:any) {
    viewer.scene.screenSpaceCameraController.enableCollisionDetection = true;
    viewer.scene.globe.translucency.enabled = false;
  }
  // 绘制遮罩层
  maskPolygon(viewer:any) {
    const $this = this;

    CreatePolygonOnGround(
      viewer,
      [],
      {
        id:$this.newSessionid(),
        color: Cesium.Color.RED.withAlpha(0.1),
        outlineColor: Cesium.Color.YELLOW,
        outlineWidth: 2,
      },
      function (polygon) {
        console.log(polygon, "polygon");

        let maskpolygonEntity = new Cesium.Entity({
          polygon: {
            hierarchy: {
              // 添加外部区域为1/4半圆，设置为180会报错
              positions: Cesium.Cartesian3.fromDegreesArray([
                0, 0, 0, 90, 179, 90, 179, 0,
              ]),
              // 中心挖空的“洞”
              holes: [
                {
                  positions: polygon.pottingPoint,
                },
              ],
            },
            material: new Cesium.Color(15 / 255.0, 38 / 255.0, 84 / 255.0, 0.7),
          },
        });
        $this.maskpolygonEntity.push(polygon);
        $this.maskpolygonEntity.push(maskpolygonEntity);

        viewer.entities.add(maskpolygonEntity);
      }
    );
  }
  //移除遮罩层
  removeMaskPolygon(viewer:any) {
    if (this.maskpolygonEntity)
      this.maskpolygonEntity.forEach((item) => viewer.entities.remove(item));
  }
  // 开始挖填方分析
  // startExcavation(viewer, option, callbackForResult) {
  //   if (!viewer.terrainProvider._layers) {
  //     if (callbackForResult && typeof callbackForResult == "function")
  //       callbackForResult("请先开启地形");
  //     return;
  //   }
  //   option.height = option.height || 70;
  //   option.precision = option.precision || 1256;
  //   var result = {
  //     allArea: 0,
  //     cutArea: 0,
  //     cutVolume: 0,
  //     fillArea: 0,
  //     fillVolume: 0,
  //     noArea: 0,
  //   };
  //   var canvas = viewer.scene.canvas;
  //   let handler = new Cesium.ScreenSpaceEventHandler(canvas);
  //   var polygon;
  //   const $this = this;
  //   const callback = (cp) => {
  //     const analysisObj = new Excavation(
  //       viewer,
  //       cp.PottingPoint.positions,
  //       option.height,
  //       option.precision,
  //       (e) => {
  //         polygon = e;
  //       }
  //     );
  //     result = analysisObj.VolumeAnalysis((e) => {
  //       $this.excavationEntity.push(e);
  //       $this.excavationEntity.forEach((item) => {});
  //     });
  //     viewer.entities.remove(cp);
  //     callbackForResult(result);
  //     // viewer.scene.screenSpaceCameraController.enableCollisionDetection = false; //允许相机进入地下
  //   };
  //   CreateRegularPolygon(
  //     viewer,
  //     handler,
  //     [],
  //     {
  //       onground: false,
  //     },
  //     callback
  //   );
  // }
  // 移除所有挖填方分析
  // removeAllExcavation(viewer) {
  //   this.excavationEntity.forEach((item) => {
  //     item.forEach((id) => {
  //       viewer.entities.removeById(id);
  //     });
  //   });
  // }
  // 开始水淹没分析
  // startWaterAnalyse(viewer, callbackForResult) {
  //   if (!viewer.terrainProvider._layers) {
  //     if (callbackForResult && typeof callbackForResult == "function")
  //       callbackForResult("请先开启地形");
  //     return;
  //   }

  //   if (viewer.scene.globe.depthTestAgainstTerrain == false)
  //     viewer.scene.globe.depthTestAgainstTerrain = true;
  //   this.changeDepth = true;
  //   const callback = (po) => {
  //     viewer.entities.remove(po);
  //     let prid = this.newSessionid(32);
  //     let waterPrimitive = new Cesium.Primitive({
  //       id: prid,
  //       allowPicking: false,
  //       asynchronous: false,
  //       geometryInstances: new Cesium.GeometryInstance({
  //         id: "initRiver",
  //         geometry: new Cesium.PolygonGeometry({
  //           polygonHierarchy: new Cesium.PolygonHierarchy(
  //             po.PottingPoint.positions
  //           ),
  //           vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
  //           extrudedHeight: 100,
  //           height: 0,
  //         }),
  //       }),
  //       appearance: new Cesium.EllipsoidSurfaceAppearance({
  //         aboveGroud: true,
  //         material: new Cesium.Material({
  //           fabric: {
  //             type: "Water",
  //             uniforms: {
  //               blendColor: new Cesium.Color(0, 0, 1, 0.3),
  //               // normalMap: require("./extend/analyse/water/water.jpg"),
  //               normalMap:
  //                 "https://img-blog.csdnimg.cn/a0130e3cafec4988916fe9e59298187b.jpeg",
  //               //频率速度设置
  //               frequency: 200,
  //               animationSpeed: 0.01,
  //               amplitude: 10,
  //             },
  //           },
  //         }),
  //       }),
  //     });
  //     this.WaterAnalyseID.push(waterPrimitive);

  //     viewer.scene.primitives.add(waterPrimitive);
  //     let enid = this.newSessionid(32);
  //     this.WaterAnalyseID.push(enid);
  //     var waterHeight = 100;
  //     viewer.entities.add({
  //       id: enid,
  //       polygon: {
  //         hierarchy: po.PottingPoint.positions,
  //         material: Cesium.Color.LIGHTBLUE.withAlpha(0.5),
  //         extrudedHeight: new Cesium.CallbackProperty(function () {
  //           return waterHeight;
  //         }, false),
  //       },
  //     });
  //     viewer.clock.onTick.addEventListener(function () {
  //       if (waterHeight > 2500) {
  //         waterHeight = 2200;
  //       }
  //       waterHeight += 0.3;
  //     });
  //   };
  //   var canvas = viewer.scene.canvas;
  //   let handler = new Cesium.ScreenSpaceEventHandler(canvas);
  //   CreateRegularPolygon(
  //     viewer,
  //     handler,
  //     [],
  //     {
  //       onground: false,
  //     },
  //     callback
  //   );
  // }
  // // 移除淹没分析
  // removeAllWaterAnalyse(viewer) {
  //   if (this.WaterAnalyseID.length > 0)
  //     this.WaterAnalyseID.forEach((item, index) => {
  //       if (index % 2 === 0) {
  //         // 偶数索引处理逻辑
  //         viewer.scene.primitives.remove(item);
  //       } else {
  //         // 单数索引处理逻辑
  //         viewer.entities.removeById(item);
  //       }
  //     });
  //   if (this.changeDepth) viewer.scene.globe.depthTestAgainstTerrain = false;
  // }
  // 添加3dtiles
  add3dtiles(viewer:any, url:any) {
    try {
      var tileset = new Cesium.Cesium3DTileset({
        url: url,
        skipLevelOfDetail: true,
        baseScreenSpaceError: 1024,
        skipScreenSpaceErrorFactor: 16,
        skipLevels: 1,
        immediatelyLoadDesiredLevelOfDetail: false,
        loadSiblings: false,
        cullWithChildrenBounds: true,
      });
      viewer.scene.primitives.add(tileset);
      tileset.tileLoad.addEventListener(function (e) {
        console.log(e.content);
      });
    } catch (error) {
      console.log(error);
    }

    return tileset;
  }
  //初始化所有图层
  initAllLayer(arr:any, viewer:any) {
    if (arr.length == 0) return;
    const map = new Map();
    arr.forEach((e) => {
      if (e.type == "3dtile") {
        let tile = this.add3dtiles(viewer, e.options.url);
        map.set(e.id, tile);
      }
    });
    return map;
  }
  expand3dTile() {}
  //设置3dtile的图层颜色
  setFeatureColor(content:any, formData:any) {
    if (content.featuresLength == 0) {
      ElMessage.error("没有找到feature");
      return;
    }
    for (var i = 0; i < content.featuresLength; ++i) {
      var feature = content.getFeature(i);
      if (feature instanceof Cesium.Cesium3DTileFeature) {
        console.log(formData[feature._batchId]);

        // var attributes = feature.getAttributes();
        var color = Cesium.Color.fromCssColorString(formData[feature._batchId]);
        feature.color = color;
      }
    }
  }
  setFeatureMaterail(content:any, formData:any) {
    console.log(formData, "formDataformData");

    if (content.featuresLength == 0) {
      ElMessage.error("没有找到feature");
      return;
    }

    for (var i = 0; i < content.featuresLength; ++i) {
      var feature = content.getFeature(i);
      if (feature instanceof Cesium.Cesium3DTileFeature) {
        console.log(formData[feature._batchId]);
        if (formData[feature._batchId]) {
          // const material = new Cesium.Material({
          //   fabric: {
          //     type: 'Image',
          //     uniforms: {
          //       image: formData[feature._batchId],
          //       channel: 'rgb',
          //     },
          //   },
          // });
          var color = Cesium.Color.fromCssColorString("#ff0000");
          var material = new Cesium.Material({
            fabric: {
              type: "Color",
              uniforms: {
                color: color,
              },
            },
          });
          const batchId = feature.getProperty("batchId");

          let model = feature.content._model;
          console.log(model, "model");

          // const model = tileset.modelInstances.get(batchId);

          // 创建材质实例
          const materialInstance = model.getMaterial("color");
          console.log(materialInstance, "materialInstance");

          const texture = new Cesium.Texture({
            url: formData[feature._batchId],
          });
          // 设置贴图材质
          materialInstance.setTexture("image", texture);
          // materialInstance.material = material;

          // let model = feature.content._model;
          // console.log(model._pipelineResources,'model');

          // if (model && model._pipelineResources) {
          // 	let program = model._pipelineResources[1];
          //   console.log(program,);
          //   console.log(program._fragmentShaderSource.sources[0],'program._fragmentShaderSource.sources[0]');

          // 	const color = `vec4(0,127.5/255.,1.,1.)`;
          // 	program._fragmentShaderSource.sources[0] = `
          // 		uniform vec2 model_iblFactor;
          // 		uniform mat3 model_iblReferenceFrameMatrix;
          // 		uniform float model_luminanceAtZenith;
          // 		uniform float u_metallicFactor;
          // 		uniform float u_roughnessFactor;
          // 		uniform int model_featuresLength;
          // 		uniform sampler2D model_batchTexture;
          // 		uniform vec4 model_textureStep;
          // 		uniform float model_colorBlend;
          // 		uniform bool model_commandTranslucent;
          // 		uniform sampler2D model_pickTexture;
          // 		varying vec3 v_positionWC;
          // 		varying vec3 v_positionEC;
          // 		varying vec3 v_normalEC;
          // 		varying vec3 v_positionMC;
          // 		varying float v_featureId_0;
          // 		struct SelectedFeature
          // 		{
          // 			int id;
          // 			vec2 st;
          // 			vec4 color;
          // 		};
          // 		struct FeatureIds
          // 		{
          // 			int featureId_0;
          // 		};
          // 		vec2 computeSt(float featureId)
          // 		{
          // 			float stepX = model_textureStep.x;
          // 			float centerX = model_textureStep.y;

          // 			#ifdef MULTILINE_BATCH_TEXTURE
          // 			float stepY = model_textureStep.z;
          // 			float centerY = model_textureStep.w;

          // 			float xId = mod(featureId, model_textureDimensions.x);
          // 			float yId = floor(featureId / model_textureDimensions.x);

          // 			return vec2(centerX + (xId * stepX), centerY + (yId * stepY));
          // 			#else
          // 			return vec2(centerX + (featureId * stepX), 0.5);
          // 			#endif
          // 		}
          // 		void selectedFeatureIdStage(out SelectedFeature feature, FeatureIds featureIds)
          // 		{
          // 			int featureId = featureIds.SELECTED_FEATURE_ID;
          // 			if (featureId < model_featuresLength)
          // 			{
          // 				vec2 featureSt = computeSt(float(featureId));

          // 				feature.id = featureId;
          // 				feature.st = featureSt;
          // 				feature.color = texture2D(model_batchTexture, featureSt);
          // 			}
          // 			else
          // 			{
          // 				feature.id = model_featuresLength + 1;
          // 				feature.st = vec2(0.0);
          // 				feature.color = vec4(1.0);
          // 			}

          // 			#ifdef HAS_NULL_FEATURE_ID
          // 			if (featureId == model_nullFeatureId) {
          // 				feature.id = featureId;
          // 				feature.st = vec2(0.0);
          // 				feature.color = vec4(1.0);
          // 			}
          // 			#endif
          // 		}
          // 		SelectedFeature selectedFeature;
          // 		void main(){
          // 			vec4 position = czm_inverseModelView * vec4(v_positionEC,1.);//获取模型的世界坐标
          // 			float buildMaxHeight = 300.0;//建筑群最高高度 配渐变色
          // 			gl_FragColor = ${color};//赋予基础底色
          // 			gl_FragColor *= vec4(vec3(position.y / buildMaxHeight ), 1.0);//根据楼层高度比例渲染渐变色
          // 			float time = abs(fract(czm_frameNumber / 360.0)-0.5)*2.;//动画频率 约束在(0,1) 更改频率修改360.0
          // 			float diffuse = step(0.005, abs(clamp(position.y / buildMaxHeight, 0.0, 1.0) - time));//根据帧数变化,光圈颜色白色,由底部朝上一丢丢(0.05)开始逐渐上移显现.
          // 			gl_FragColor.rgb += gl_FragColor.rgb * (1.0 - diffuse );//单纯叠加颜色 感兴趣的可以mix混合下
          // 		}
          // 	`;
          // }
        }
      }
    }
  }
  // 移动3dtile
  moveB3DM(viewer:any, b3dm:any) {
    this.editObj = new EditB3DM(viewer, b3dm, 1, 1);
    this.editObj.editTranslation();
  }
  // 转动3dtile
  rotateB3DM(viewer:any,b3dm:any) {
    this.editObj = new EditB3DM(viewer, b3dm, 1, 1);
    this.editObj.editRtation();
  }
  // //取消编辑
  editB3DMdestroy() {
    this.editObj.destroy();
  }
  // 截图
  captureScreen(viewer:any) {
    return new Promise((resolve, reject) => {
      captureScreenshot(viewer).then((blob) => {
        blobToBase64(blob).then((res) => {
          resolve(res);
        }).catch((error) => {
          console.error(error);
          reject(error);
        });
      }).catch((error) => {
        console.error(error);
        reject(error);
      });
    });
  }

}
